home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 361_02 / valve.c < prev    next >
C/C++ Source or Header  |  1991-09-18  |  7KB  |  193 lines

  1.  
  2. /* (#) VALVE --> Pass or WOM stdin => stdout.  Trip on NL or Specified CHR$.
  3.  *
  4.  * Author: J.Ekwall 23 November 1987.
  5.  *
  6.  * Copyrighted to the Public Domain.  Unlimited Distribution Autorized.
  7.  *
  8.  * User Assumes All Risks/Liabilities.
  9.  *
  10.  * Last Update:  5 December 89/EK
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <io.h>
  17. #include <string.h>
  18. #include <stdek.h>
  19.  
  20. char *Documentation[] = {
  21.     "",
  22.     "Usage:",
  23.     "       Valve [options] [filename] --> Control Text Flow.",
  24.     "",
  25.     "Options:",
  26.     "          /An ---> Trip on the \"n\"th Trigger Character. [D:1]",
  27.     "          /B ----> Block Text Until Triggered.",
  28.     "          /Cc ---> Trigger on 'c' vice NL.  'c' is any Printable.",
  29.     "                   or $$ or $### (3 Decimal Digits) for any ASCII.",
  30.     "          /F ----> FIFO for Lines.  Pops Top Line Each Call.",
  31.     "          /Hn ---> Pass Head (Top) n Lines.  [D:10]",
  32.     "          /I ----> Initial Character Trips.  (Ignore Everything Else).",
  33.     "                   /C option Required.",
  34.     "          /J ----> Jog.  (Trip Twice & Hold Initial State).",
  35.     "          /L-----> LIFO for Lines.  Pops Last Line Each Call.",
  36.     "          /Tn ---> Pass Tail (Bottom) n Lines.  [D:10]",
  37.     "          /V ----> Verbose.  Echo Text to CRT Until Triggered.",
  38.     "",
  39.     "   Valve defaults to a Filter.  $Pipes are Legal in filename.",
  40.     "",
  41.     "   After Loading, Repeated /F or /L Calls Pop Lines until Stack/Queue ",
  42.     "is Empty.  Text is Stored in the Named Pipe, $VALV.",
  43.     "",
  44.     NULL };
  45.  
  46. /* Define Constants */
  47. #define PIPE    "\\STD VALV"
  48. #define PUKA    "\\STD VPUK"            /* "Puka" Hawaiia for Pigeon Hole */
  49.  
  50. /* Declare Globale */
  51. int CleanUp, Flow_Mode;;
  52. char Name[80];
  53. FILE *fp = stdin;
  54.  
  55. /* Declare ProtoTypes */
  56. void Usage(void);
  57.  
  58. main (int argc, char *argv[])
  59. {
  60.     int c, i, n, Count = 0, NL_Flag, Trip_Chr = NL;
  61.     int Echo = FALSE, Flow = TRUE, Save = FALSE, Tail = FALSE, Ignore = FALSE;
  62.     int Jog = FALSE, Fifo = FALSE, Lifo = FALSE, Lines_Only = FALSE;
  63.     char *tp1;
  64.     FILE *wfp;
  65.  
  66.  /* Set Option Flags */
  67.     while (*argv[1] IS SLASH) {
  68.        for (tp1 = argv[1] + 1; *tp1 != NULL; ) {
  69.           switch (toupper(*tp1++)) {
  70.           case 'A':                             /* Action Skip Count */
  71.              if (Count > 0) Usage();
  72.              for (Count = 0; (*tp1 >= '0') && (*tp1 <= '9'); tp1++)
  73.                 Count = 10 * Count + *tp1 - 48;
  74.              if (Count > 0) --Count;
  75.              break;
  76.           case 'B': Flow = FALSE; break;        /* Block to Start */
  77.           case 'C':                             /* Trigger Character Change */
  78.              if ((c = (BYTE) *tp1++) IS '$') {
  79.                 for (c = 0; (*tp1 >= '0') && (*tp1 <= '9'); tp1++)
  80.                    c = 10 * c + *tp1 - 48;
  81.                 if ((c IS 0) && (*tp1 IS '$')) { c = '$';  tp1++; }
  82.              }
  83.              Trip_Chr = c; if (Trip_Chr IS 0) Usage();
  84.              break;
  85.           case 'F': Fifo = Save = Lines_Only = TRUE; break;
  86.           case 'H':                             /* Head */
  87.              Lines_Only = TRUE;
  88.              for (Count = -1; (*tp1 >= '0') && (*tp1 <= '9'); tp1++)
  89.                 Count = 10 * Count + *tp1 - 48;
  90.              if (Count < 0) Count = 9;
  91.              break;
  92.           case 'I': Ignore = TRUE; break;
  93.           case 'J': Jog = TRUE; break;
  94.           case 'L': Lifo = Save = Lines_Only = Tail = TRUE; break;
  95.           case 'T':                             /* Tail */
  96.              Tail = Lines_Only = TRUE;
  97.              for (Count = 0; (*tp1 >= '0') && (*tp1 <= '9'); tp1++)
  98.                 Count = 10 * Count + *tp1 - 48;
  99.              if (Count IS 0) Count = 10;
  100.              break;
  101.           case 'V':     /* Verbose */
  102.              Echo = TRUE; break;
  103.           default:
  104.              fprintf(stderr,"\nInvalid Option [%s].\n\n",argv[1]);
  105.              Usage();
  106.           }
  107.        }
  108.  
  109.     /* SHIFT */
  110.        for (i = 1, --argc; i < argc + 1; i++) argv[i] = argv[i+1];
  111.     }
  112.  
  113.  /* Validate Options & Flags */
  114.     if (Fifo && Lifo) Usage();
  115.     if (Jog && (Lifo || Fifo)) Usage();
  116.     if ((Trip_Chr != NL) && Lines_Only) Usage();
  117.     if ((Trip_Chr IS NL) && Ignore) Usage();
  118.     if (argc > 2) Usage();
  119.  
  120.  /* Open Specified File (If Any) */
  121.     if (argc IS 2)
  122.        if (*argv[1] IS '$') {
  123.           strcpy(Name,"\\STD "); strcat(Name,++argv[1]);
  124.           if ((fp = fopen(Name,"r")) IS NULL) { perror(Name); exit(1); }
  125.           CleanUp = TRUE;
  126.        } else {
  127.           strcpy(Name,argv[1]);
  128.           if ((fp = fopen(Name,"r")) IS NULL) { perror(Name); Usage(); }
  129.           CleanUp = FALSE;
  130.        }
  131.  
  132.  /* Check for Piping */
  133.     if (!Save && !INFLOW_EXISTS && (fp IS stdin)) Usage();
  134.  
  135.  /* Set Up Streams & Pigeon Holes */
  136.     if ((Save) && !(INFLOW_EXISTS) && (fp IS stdin))
  137.        if ((fp = fopen(PIPE,"r")) IS NULL) exit(0);
  138.     if (Tail || Save) {                         /* Stuff Pigeon Hole File */
  139.        if (Tail) {
  140.           Count = -(++Count); Flow = !Flow; if (Fifo || Lifo) Count--; }
  141.        if ((wfp = fopen(PUKA,"w")) IS NULL) { perror(PUKA); exit(1); }
  142.        while ((c = getc(fp)) != EOF) {
  143.           if ((c IS Trip_Chr) && (Tail)) Count++; /* Figure Offset fm SOF */
  144.           putc(c,wfp);
  145.        }
  146.        fclose(fp); fclose(wfp);
  147.        if ((fp = fopen(PUKA,"r")) IS NULL) { perror(PUKA); exit(1); }
  148.     }
  149.     if (Save) if ((wfp = fopen(PIPE,"w")) IS NULL) { perror(PIPE); exit(1); }
  150.  
  151.  /* Perform Pass/Block Action */
  152.     for (NL_Flag = TRUE; (c = getc(fp)) != EOF ; NL_Flag = (c IS NL)) {
  153.        if (c IS Trip_Chr) {
  154.           if (!NL_Flag && Ignore) Count++;
  155.           if (Count-- IS 0) {
  156.              if (Trip_Chr IS NL) {      /* Terminate Hanging Line */
  157.                 if (Flow IS TRUE) putchar(c);
  158.                 if ((!Flow) && (Save)) putc(c,wfp);
  159.                 if (Echo) putc(c,stderr);
  160.              }
  161.              Echo = FALSE;
  162.              if ((Flow = !Flow) IS FALSE)
  163.                 if (!Save && !Jog) break;
  164.              if (Jog) {Jog = FALSE; Count = 0; }
  165.              continue;
  166.           }
  167.        }
  168.        if (Flow IS TRUE) putchar(c);
  169.        if ((!Flow) && (Save)) putc(c,wfp);
  170.        if (Echo) putc(c,stderr);
  171.     }
  172.  
  173.  /* CleanUp & Split */
  174.     if (CleanUp IS TRUE) { fclose(fp); unlink(Name); }
  175.     if (fp != NULL) { fclose(fp); unlink(PUKA); }
  176.     if (wfp != NULL) {  /* Zip MT Pipes */
  177.        fclose(wfp);
  178.        if ((fp = fopen(PIPE,"r")) != NULL) {
  179.           c = getc(fp); fclose(fp); if (c IS EOF) unlink(PIPE); }
  180.     }
  181.     exit(0);
  182. }
  183.  
  184.  
  185. void Usage(void)
  186. {
  187.     char   **dp = Documentation;
  188.  
  189.     for ( ; *dp; dp++) fprintf(stderr,"%s\n", *dp);
  190.     exit(1);
  191. }
  192.  
  193.